<?php
//后根序遍历目录, 读取所有子目录和文件
//生成文件列表, 但不包含 以"."开头的目录或文件
//张志斌 954861399@qq.com
class Dir
{
	public $dir = '';
	public $fileList = [];
    public $fileHashChain = []; //存放每个路径的哈希链, 'a/b/c/file.md' => [md5(a), md5(a/b), md5(a/b/c), md5(a/b/c/file.md)]

    //遍历文件
	public function __construct($dir)
	{
        $stack = array();
        $dir = str_replace('\\', '/', realpath($dir));
        $current = [
            'dir' => $dir.'/',
            'files' => $this->getDirFiles($dir)
        ];
    
        while(!empty($stack) || !empty($current['files'])){
            $isStack = 0;
            foreach ($current['files'] as $k => $fileName) {
                $pathName = $current['dir'].$fileName;
                if (is_file($pathName)) {
                    $this->fileList[] = $pathName;
                } elseif (is_dir($pathName) && count($this->getDirFiles($pathName)) > 0) {
                    //当前是目录, 就把其以后的数据压栈
                    $tmp['files'] = array_slice($current['files'], $k+1);
                    $tmp['dir'] = $current['dir'];
                    array_push($stack, $tmp);
                    $isStack = 1;
                
                    $current['files'] = $this->getDirFiles($pathName); //读当前目录中的文件
                    $current['dir'] = $pathName.'/';
                
                    break;
                }
            }
        
            if (empty($isStack)) { //没有入栈, 说明当前目录里全是文件
                $current = array_pop($stack); //读取栈里保存的目录/文件
            }
        }
        
        foreach ($this->fileList as $k => $v) {
            $this->fileList[$k] = str_replace('\\', '/', $v);
        }
    }
    
    //读取所有子目录和文件, $dir目录最后不要有'/'
    public static function ini($dir)
    {
        return new self($dir);
    }
    
    public function getDirFiles($dir)
    {
        $list = [];
        $files = scandir($dir);
        foreach ($files as $fileName) {
            if (substr($fileName, 0, 1) != '.') {
                $list[] = $fileName;
            }
        }
        
        return $list;
    }
    
    //替换路径里的字符串
    public function replace($target, $replace='')
    {
        foreach ($this->fileList as $k => $v) {
            $this->fileList[$k] = str_replace($target, $replace, $v);
        }
        return $this;
    }
    
    //替换路径里的字符串
    public function pregReplace($pattern, $replace='')
    {
        foreach ($this->fileList as $k => $v) {
            $this->fileList[$k] = preg_replace("#$pattern#i", $replace, $v);
        }
        return $this;
    }

	//筛选获取指定的后缀
    // $ext, 多个后缀用逗号隔开
	public function extension($ext)
	{
	    $arr = explode(',', $ext);
		foreach ($this->fileList as $k => $v) {
			$extension = pathinfo($v, PATHINFO_EXTENSION);
			if (!in_array(strtolower($extension), $arr)) {
				unset($this->fileList[$k]);
			}
		}
		return $this;
	}
	
	public function sortFiles($isReverse = FALSE)
    {
        if ($isReverse) {
            rsort($this->fileList);
        } else {
            sort($this->fileList);
        }
        
        return $this;
    }
    
    //生成hash值, 避免中文乱码, 以及减少长度
    public function getHash($str, $len=16)
    {
        return substr(md5($str), 0, $len);
    }


    public function createHashChain()
    {
        foreach ($this->fileList as $filePath) {
            $arr = explode('/', $filePath);
            $tmp = [];
            foreach ($arr as $v) {
                $tmp[] = $v;
                $str = implode('/', $tmp);
                $this->fileHashChain[$filePath][] = $this->getHash($str);
            }
        }
        return $this;
    }
    
}